/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package etherblocks.engine.states;

import java.io.File;
import java.io.FileFilter;
import com.jme3.app.Application;
import com.jme3.app.state.AppStateManager;
import com.jme3.math.Vector3f;
import etherblocks.engine.*;
import etherblocks.engine.files.*;
import etherblocks.game.*;
import com.cubes.BlockTerrainControl;
import com.cubes.Vector3Int;
import com.cubes.network.CubesSerializer;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

/**
 *
 * @author Carl
 */
public class WorldFileHandlerAppState extends BaseAppState{

    public WorldFileHandlerAppState(){
        
    }    
    public static String WORLDS_DIRECTORY = "./worlds/";
    public static String WORLD_FILE_SUFFIX = ".world";
    private static final int XML_BYTE_OFFSET = 0x20;
    private static final String VECTOR_COORDINATES_SEPARATOR = ",";
    
    @Override
    public void initialize(AppStateManager stateManager, Application application){
        super.initialize(stateManager, application);
        FileManager.createDirectoryIfNotExists(WORLDS_DIRECTORY);
    }
    
    public  void saveFile_DefaultDirectory(String name, World world){
        saveFile(new File(WORLDS_DIRECTORY + name + WORLD_FILE_SUFFIX), world);
    }
    
    public void saveFile(File file, World world){
        try{
            Element root = new Element("world");
            root.setAttribute("author", System.getProperty("user.name"));
            root.setAttribute("date", "" + System.currentTimeMillis());
            Document document = new Document(root);
            Element elementTerrain = new Element("blockTerrain");
            byte[] serializedTerrainData = CubesSerializer.writeToBytes(world.getBlockTerrain());
            for(int i=0;i<serializedTerrainData.length;i++){
                serializedTerrainData[i] += XML_BYTE_OFFSET;
            }
            elementTerrain.setText(new String(serializedTerrainData, "UTF8"));
            root.addContent(elementTerrain);
            FileManager.putFileContent(file.getPath(), new XMLOutputter().outputString(document));
        }catch(Exception ex){
            System.out.println("Error while saving the world.");
            ex.printStackTrace();
        }
    }

    public World loadFile_DefaultDirectory(String name){
        return loadFile(new File(WORLDS_DIRECTORY + name + WORLD_FILE_SUFFIX));
    }

    public World loadFile(File file){
        World world = new World();
        try{
            Document document = new SAXBuilder().build(file);
            Element root = document.getRootElement();
            String worldName = file.getName().substring(0, (file.getName().length() - WORLD_FILE_SUFFIX.length()));
            WorldInformation worldInformation = new WorldInformation(worldName, root.getAttributeValue("author"), root.getAttribute("date").getLongValue());
            byte[] serializedTerrainData = root.getChild("blockTerrain").getText().getBytes("UTF8");
            for(int i=0;i<serializedTerrainData.length;i++){
                serializedTerrainData[i] -= XML_BYTE_OFFSET;
            }
            BlockTerrainControl blockTerrain = new BlockTerrainControl(CubesConfiguration.getSettings(mainApplication), new Vector3Int());
            CubesSerializer.readFromBytes(blockTerrain, serializedTerrainData);
            world.setBlockTerrain(blockTerrain);
            world.setWorldInformation(worldInformation);
        }catch(Exception ex){
            System.out.println("Error while loading the world.");
            ex.printStackTrace();
        }
        return world;
    }
    
    private static Element getVector3IntElement(String tagName, Vector3Int vector3Int){
        Element elementVector = new Element(tagName);
        elementVector.setText(vector3Int.getX() + VECTOR_COORDINATES_SEPARATOR + vector3Int.getY() + VECTOR_COORDINATES_SEPARATOR + vector3Int.getZ());
        return elementVector;
    }
    
    private static Vector3Int getVector3Int(Element elementVector){
        int[] coordinates = Util.parseToIntArray(elementVector.getText().split(VECTOR_COORDINATES_SEPARATOR));
        return new Vector3Int(coordinates[0], coordinates[1], coordinates[2]);
    }
    
    private static Element getVector3fElement(String tagName, Vector3f vector3f){
        Element elementVector = new Element(tagName);
        elementVector.setText(vector3f.getX() + VECTOR_COORDINATES_SEPARATOR + vector3f.getY() + VECTOR_COORDINATES_SEPARATOR + vector3f.getZ());
        return elementVector;
    }
    
    private static Vector3f getVector3f(Element elementVector){
        float[] coordinates = Util.parseToFloatArray(elementVector.getText().split(VECTOR_COORDINATES_SEPARATOR));
        return new Vector3f(coordinates[0], coordinates[1], coordinates[2]);
    }
    
    public static File[] getMapFiles(String subDirectory){
        return new File(WORLDS_DIRECTORY + subDirectory).listFiles(new FileFilter(){

            public boolean accept(File file){
                return file.getPath().endsWith(WORLD_FILE_SUFFIX);
            }
        });
    }
}
